package com.tgjorgoski.sidekicknotes.rtfview.support;

import java.awt.event.ActionEvent;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.text.*;

import org.apache.log4j.Logger;
import org.matheclipse.core.eval.EvalEngine;
import org.matheclipse.script.engine.MathScriptEngine;
import org.matheclipse.script.engine.MathScriptEngineFactory;

import com.tgjorgoski.window.Session;

public class EvaluateSupport {
	Action evaluateLine;
	public static final String ACTION_KEY = "evaluate-line";
	private static EvaluateSupport instance;
	private ScriptEngineManager manager;
	private ScriptEngine scriptEngine;
	private Logger logger = Logger.getLogger(EvaluateSupport.class);
	
	public static EvaluateSupport getInstance() {
		if (instance==null) {
			instance=new EvaluateSupport();
		}
		return instance;
	}
	
	private EvaluateSupport() {
		/*ScriptEngineManager  manager = new ScriptEngineManager();
		scriptEngine = manager.getEngineByName("JavaScript");*/
		
		MathScriptEngineFactory msef = new MathScriptEngineFactory();
		scriptEngine = msef.getScriptEngine();
		evaluateLine = new EvaluateLine();
	}
	
	public void registerComponent(JTextComponent comp) {
		comp.getActionMap().put(ACTION_KEY, evaluateLine);
	}
	
	public Action getEvaluateAction() {
		return evaluateLine;
	}
	
	public class EvaluateLine extends TextAction {
		public EvaluateLine() {
			super(ACTION_KEY);
		}

		public void actionPerformed(ActionEvent e) {
			JTextComponent comp = getTextComponent(e);
			if (comp!=null) {
				//check what should be evaluated... if we don't have selected text, use the current line
				String text = comp.getSelectedText();
				int end = comp.getSelectionEnd();
				if (text==null || text.length()==0) {
					int cPosition = comp.getCaretPosition();
					Document doc = comp.getDocument();
					if (doc instanceof StyledDocument) {
						StyledDocument sDoc = (StyledDocument)doc;
						Element el = sDoc.getParagraphElement(cPosition);
						int sOffset = el.getStartOffset();
						int eOffset = el.getEndOffset();
						try {
							text = comp.getText(sOffset, eOffset-sOffset);
							end=eOffset-1;
						} catch (BadLocationException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					}
				}

				String valueStr=null;
				if (text!=null && text.length()!=0) {
					Object valueO;
					StringWriter defaultOutput=new StringWriter();
					try {
						String trimmedText = text.trim();
						scriptEngine.getContext().setWriter(new PrintWriter(defaultOutput));
						valueO = scriptEngine.eval(trimmedText);
						
						if (valueO!=null) {
							if (valueO instanceof Double) {
								Double dbl = (Double)valueO;
								if (dbl.intValue()==dbl) {
									valueO=dbl.intValue();
								}
							} else if (valueO instanceof Float) {
								Float flt = (Float)valueO;
								if (flt.intValue()==flt) {
									valueO = flt.intValue();
								}
							}
							valueStr=valueO.toString();
						} else {
							valueStr = defaultOutput.toString();
						}
					} catch(ScriptException exc) {
						JOptionPane.showMessageDialog(Session.getHTMLView(), "Problem evaluating selected text:\n" + exc.toString());
					}
				}
				if (valueStr!=null) {
					try {
						comp.setCaretPosition(end);
						comp.getDocument().insertString(end, "\n--------\n"+valueStr, null);
					} catch (BadLocationException e1) {
						// TODO Auto-generated catch block
						logger.error("Problem while inserting evaluated result into the document", e1);
					}
				}
			}
		}
	}
}
